package com.kingdee.eas.deppon.journal;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.bos.dao.IObjectPK;
import com.kingdee.bos.metadata.entity.EntityViewInfo;
import com.kingdee.bos.metadata.entity.FilterInfo;
import com.kingdee.bos.metadata.entity.FilterItemInfo;
import com.kingdee.bos.metadata.query.util.CompareType;
import com.kingdee.bos.util.BOSUuid;
import com.kingdee.eas.base.permission.UserFactory;
import com.kingdee.eas.base.permission.UserInfo;
import com.kingdee.eas.base.vc.VerifyScopeEnum;
import com.kingdee.eas.basedata.assistant.AccountBankFactory;
import com.kingdee.eas.basedata.assistant.AccountBankInfo;
import com.kingdee.eas.basedata.assistant.CurrencyFactory;
import com.kingdee.eas.basedata.assistant.CurrencyInfo;
import com.kingdee.eas.basedata.assistant.PeriodFactory;
import com.kingdee.eas.basedata.assistant.PeriodInfo;
import com.kingdee.eas.basedata.assistant.SettlementTypeFactory;
import com.kingdee.eas.basedata.assistant.SettlementTypeInfo;
import com.kingdee.eas.basedata.assistant.VoucherTypeFactory;
import com.kingdee.eas.basedata.assistant.VoucherTypeInfo;
import com.kingdee.eas.basedata.master.account.AccountViewFactory;
import com.kingdee.eas.basedata.master.account.AccountViewInfo;
import com.kingdee.eas.basedata.org.CompanyOrgUnitFactory;
import com.kingdee.eas.basedata.org.CompanyOrgUnitInfo;
import com.kingdee.eas.basedata.org.CtrlUnitInfo;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.eas.fi.cas.BillTypeEnum;
import com.kingdee.eas.fi.cas.IJournal;
import com.kingdee.eas.fi.cas.JournalCollection;
import com.kingdee.eas.fi.cas.JournalFactory;
import com.kingdee.eas.fi.cas.JournalInfo;
import com.kingdee.eas.fi.cas.JournalSourceEnum;
import com.kingdee.eas.fi.cas.JournalTypeEnum;
import com.kingdee.eas.fm.common.ContextHelperFactory;
import com.kingdee.eas.interfaces.util.OrgUtils;

public class JournalFacadeControllerBean extends AbstractJournalFacadeControllerBean {
	private static final long serialVersionUID = 1L;
	private static Logger logger = Logger.getLogger("com.kingdee.eas.deppon.journal.JournalFacadeControllerBean");

	/**
	 * 新增日记账信息
	 * 
	 * @param objectString
	 *            第三方系统传过来的JSONArray字符串
	 * @author 刘鹏
	 * @serialData 2013-7-18
	 */
	public String addJournal(Context ctx, String objectString) throws BOSException {
		logger.info("新增银行日记账...");
		long before = System.currentTimeMillis();
		JSONArray array = null;
		try {
			logger.info("解析json字符串...");
			array = new JSONArray(objectString);
		} catch (JSONException e) {
			return "解析JSON字符串出错,请确定JSON字符串是否正确." + e.getMessage();
		}

		logger.info("获取日记账集合...");
		JournalCollection journalCollection = null;
		try {
			journalCollection = this.getJournalCollectionByJSONArray(ctx, array);
		} catch (JSONException e1) {
			return "解析JSONArray出错,请确认数据正确性!" + e1.getMessage();
		}

		logger.info("批量保存银行日记账信息...");
//		try {
			try {
				JournalFactory.getLocalInstance(ctx).addBatch(journalCollection);
			} catch (EASBizException e) {
				e.printStackTrace();
			}
//		} catch (EASBizException e) {
//			return "新增银行日记账出错." + e.getMessage();
//		}

		long after = System.currentTimeMillis();
		logger.info("保存银行日记账成功,耗时:" + (after - before) / 1000 + "秒!");
		return "新增日记账数据成功,耗时:" + (after - before) / 1000 + "秒!";

	}

	/**
	 * 解析JSONArray
	 * 
	 * @param array
	 * @return
	 * @throws JSONException
	 * @throws BOSException
	 * @author 刘鹏
	 * @serialData 2013-7-18
	 */
	private JournalCollection getJournalCollectionByJSONArray(Context ctx, JSONArray array) throws JSONException, BOSException {
		JournalCollection journals = new JournalCollection();
		for (int i = 0; i < array.length(); i++) {
			JournalInfo journal = this.getJournalByJSONObject(ctx, array.getJSONObject(i));
			if (journal != null)
				journals.add(journal);
		}
		return journals;
	}

	/**
	 * 解析JSONObject
	 * 
	 * @param array
	 * @return
	 * @throws JSONException
	 * @throws BOSException
	 * @author 刘鹏
	 * @serialData 2013-7-18
	 */
	private JournalInfo getJournalByJSONObject(Context ctx, JSONObject object) throws JSONException, BOSException {
		logger.info("解析JSONObject...");

		JournalInfo journal = new JournalInfo();
		//设置ID
		journal.setId(BOSUuid.create(journal.getBOSType()));

		// 获取公司信息
		if (!isExistAttribute("company", object))
			throw new BOSException("参数公司编码不能为空!");
		String companyNumber = object.getString("company");
		CompanyOrgUnitInfo company = CompanyOrgUnitFactory.getLocalInstance(ctx).getCompanyOrgUnitCollection("where number='" + companyNumber + "'").get(0);
		if (company == null)
			throw new BOSException("公司:" + companyNumber + " ,请确认传的数据是否正确!");

		journal.setCompany(company);

		// 获取CU
		CtrlUnitInfo unitInfo = new OrgUtils().getPreOrg(ctx, company.getString("id"));
		if (unitInfo != null)
			journal.setCU(unitInfo);
		
		//获取当前期间
		if(!isExistAttribute("period", object))
			throw new BOSException("参数期间不能为空!");
		int period=object.getInt("period");
		PeriodInfo periodInfo=PeriodFactory.getLocalInstance(ctx).getPeriodCollection("where number="+period).get(0);
		if(periodInfo==null)
			throw new BOSException("期间:"+period+"不存在!");
		//判断是否为调整期间
		if(periodInfo.isIsAdjustPeriod())
			throw new BOSException("期间为调整期，不能登账！");
		journal.setPeriod(periodInfo);
		journal.setCreateDate(periodInfo.getBeginDate());
		
		// 获取银行账户
		if (!isExistAttribute("accountBank", object))
			throw new BOSException("参数银行账户编码不能为空!");

		String accountBankNumber = object.getString("accountBank");
		AccountBankInfo accountBank = AccountBankFactory.getLocalInstance(ctx).getAccountBankCollection("where number='" + accountBankNumber + "'").get(0);

		if (accountBank == null)
			throw new BOSException("银行账户: " + accountBankNumber + "不存在 ,请确认传的数据是否正确!");

		journal.setAccountBank(accountBank);

		// 获取科目信息
		if (!isExistAttribute("accountView", object))
			throw new BOSException("参数科目编码不能为空!");

		String accountViewNumber = object.getString("accountView");
		AccountViewInfo accountViewInfo = AccountViewFactory.getLocalInstance(ctx).getAccountViewCollection("where number='" + accountViewNumber + "' and companyID='"+company.getString("id")+"'").get(0);
		if (accountViewInfo == null) {
			throw new BOSException("会计科目:" + accountViewNumber + " 不存在,请确认数据是否正确!");
		}
		journal.setAccountView(accountViewInfo);

		// 币别
		if (!isExistAttribute("currency", object))
			throw new BOSException("参数币别编码不能为空!");

		String currencyNumber = object.getString("currency");
		CurrencyInfo currencyInfo = CurrencyFactory.getLocalInstance(ctx).getCurrencyCollection("where number='" + currencyNumber + "'").get(0);
		if (currencyInfo == null)
			throw new BOSException("币别:" + currencyNumber + "不存在,请确认传的数据是否正确!");
		journal.setCurrency(currencyInfo);

		// 结算类型
		if (!isExistAttribute("settlementType", object))
			throw new BOSException("参数结算类型编码不能为空!");
		String settlementTypeNumber = object.getString("settlementType");
		EntityViewInfo ev = new EntityViewInfo();
		FilterInfo fi = new FilterInfo();
		fi.getFilterItems().add(new FilterItemInfo("number", settlementTypeNumber));
		ev.setFilter(fi);
		SettlementTypeInfo settlementTypeInfo = SettlementTypeFactory.getLocalInstance(ctx).getSettlementTypeCollection(ev).get(0);
		if (settlementTypeInfo == null)
			throw new BOSException("结算类型:" + settlementTypeNumber + "不存在,请确认传的数据是否正确!");
		journal.setSettlementType(settlementTypeInfo);

		// 借贷方向 借贷金额 0借 1贷
		if (!isExistAttribute("isDebit", object))
			throw new BOSException("参数借贷方向不能为空!");

		boolean isDebit = object.getBoolean("isDebit");
		journal.setIsDebit(isDebit);

		// 根据借贷方向获取借贷方向的金额
		if (isDebit) {
			if (isExistAttribute("debitAmount", object)) {
				double debitAmount = object.getDouble("debitAmount");
				journal.setDebitAmount(new BigDecimal(debitAmount));
			} else {
				throw new BOSException("参数借方金额不能为空!");
			}
		} else {
			if (isExistAttribute("debitAmount", object)) {
				double creditAmount = object.getDouble("creditAmount");
				journal.setCreditAmount(new BigDecimal(creditAmount));
			} else {
				throw new BOSException("参数贷方金额不能为空!");
			}
		}

		// 结算号
		if (isExistAttribute("settlementNumber", object))
			journal.setSettlementNumber(object.getString("settlementNumber"));

		// 业务日期
		if (!isExistAttribute("assisDate", object))
			journal.setAssisDate(new Date());
		else {
			String dateString = object.getString("assisDate");
			try {
				journal.setAssisDate(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(dateString));
			} catch (ParseException e) {
				throw new BOSException("业务日期格式错误!(yyyy-MM-dd hh:mm:ss)");
			}
		}

		// 对方科目
		if (isExistAttribute("oppAccountView", object)) {
			AccountViewInfo oppAccountView = AccountViewFactory.getLocalInstance(ctx).getAccountViewCollection("where number='" + object.getString("oppAccountView") + "'").get(0);

			if (oppAccountView == null)
				throw new BOSException("对方科目编码:" + object.getString("oppAccountView") + "不存在!");
			journal.setOppAccountView(oppAccountView);
		}

		// 对方单位
		if (isExistAttribute("oppUnit", object))
			journal.setOppUnit(object.getString("oppUnit"));

		// 对方账号
		if (isExistAttribute("oppAcctNumber", object))
			journal.setOppAcctNumber(object.getString("oppAcctNumber"));

		// 对方银行
		if (isExistAttribute("oppBank", object))
			journal.setOppBank(object.getString("oppBank"));

		// 凭证类型
		if (isExistAttribute("voucherType", object)) {
			EntityViewInfo evi = new EntityViewInfo();
			FilterInfo ef = new FilterInfo();
			String voucherTypeName = object.getString("voucherType");
			ef.getFilterItems().add(new FilterItemInfo("name", voucherTypeName));
			evi.setFilter(ef);
			VoucherTypeInfo voucherType = VoucherTypeFactory.getLocalInstance(ctx).getVoucherTypeCollection(evi).get(0);
			if (voucherType == null)
				throw new BOSException("凭证类型:" + voucherTypeName + "不存在!");
			journal.setVoucherType(voucherType);
		}

		// 凭证号
		if (isExistAttribute("voucherNumber", object))
			journal.setVoucherNumber(object.getString("voucherNumber"));

		// 单据号
		if (isExistAttribute("billNumber", object))
			journal.setBillNumber(object.getString("billNumber"));

		// 摘要
		if (isExistAttribute("description", object))
			journal.setDescription(object.getString("description"));
		
		//出纳
		if(isExistAttribute("cashier", object)){
			try {
				String cashierNumber=object.getString("cashier");
				UserInfo cashier=UserFactory.getLocalInstance(ctx).getUserCollection("where number='"+cashierNumber+"'").get(0);
				if(cashier==null)
					journal.setCashier(ContextHelperFactory.getLocalInstance(ctx).getCurrentUser());
				else
					journal.setCashier(cashier);
			} catch (Exception e) {
				
			}
		}
		
		//单据类型
		if(isExistAttribute("billType", object)){
			int billType=object.getInt("billType");
			BillTypeEnum type=BillTypeEnum.getEnum(billType);
			journal.setBillType(type);
		}else{
			throw new BOSException("参数单据类型不能为空,请确认参数是否完整!");
		}
		
		//日记账类型
		if(isExistAttribute("type", object)){
			int typevalue=object.getInt("type");
			JournalTypeEnum type = JournalTypeEnum.getEnum(typevalue);
			journal.setType(type);
		}
		//业务日期
		journal.setBizDate(new Date());
		
		//勾兑状态
		journal.setVerifyStatus(VerifyScopeEnum.NOVA);
		
		//日记账来源
		journal.setSource(JournalSourceEnum.BYIMPORT);
		return journal;
	}

	/**
	 * 验证JSONObject是否有这个key
	 * 
	 * @param key
	 * @param jo
	 * @return
	 * @throws JSONException
	 * @author 刘鹏
	 * @editDate 2013-7-30
	 */
	private boolean isExistAttribute(String key, JSONObject jo){
		try {
			return jo.get(key) != null;
		} catch (JSONException e) {
			return false;
		}
	}

	/**
	 * 删除银行日记账
	 * 
	 * @param condition
	 *            JSON条件字符串
	 * @author 刘鹏
	 * @editDate 2013-7-30
	 */
	public String deleteJournal(Context ctx, String condition) throws BOSException {
		logger.info("删除银行日记账.....");
		long before = System.currentTimeMillis();
		FilterInfo fi = conditionToFilterInfo(condition);

		// 删除银行日记账
		IObjectPK[] pks = null;
		try {
			pks = JournalFactory.getLocalInstance(ctx).delete(fi);
		} catch (EASBizException e) {
			throw new BOSException("删除银行日记账出错:" + e.getMessage());
		}
		long after = System.currentTimeMillis();

		return "删除" + pks.length + "条日记账数据,耗时:" + (after - before) / 1000 + "秒!";
	}

	/**
	 * 红冲银行日记账
	 * 
	 * @param condition
	 *            JSON条件字符串
	 * @author 刘鹏
	 * @editDate 2013-7-30
	 */
	public String redPunch(Context ctx, String condition) throws BOSException {
		logger.info("红冲银行日记账...");
		long before = System.currentTimeMillis();
		FilterInfo fi = conditionToFilterInfo(condition);
		EntityViewInfo ev = new EntityViewInfo();
		ev.setFilter(fi);

		logger.info("获取远程接口...");
		IJournal journalBiz = JournalFactory.getLocalInstance(ctx);
		JournalCollection journals = journalBiz.getJournalCollection(ev);

		logger.info("红冲...");
		JournalCollection newjournals = new JournalCollection();

		for (int i = 0; i < journals.size(); i++) {
			JournalInfo newJournal = (JournalInfo) journals.get(i).clone();
			if (newJournal.isIsDebit()) {
				newJournal.setDebitAmount(new BigDecimal(0).subtract(newJournal.getDebitAmount()));
			} else {
				newJournal.setCreditAmount(new BigDecimal(0).subtract(newJournal.getCreditAmount()));
			}
			newJournal.setId(BOSUuid.create("DF8E708B"));
			newjournals.add(newJournal);
		}
		try {
			logger.info("批量执行...");
			journalBiz.addBatch(newjournals);
		} catch (EASBizException e) {
			throw new BOSException("红冲银行日记账错误:" + e.getMessage());
		}

		long after = System.currentTimeMillis();
		return "红冲日记账完成,耗时:" + (after - before) / 1000 + "秒!";
	}

	/**
	 * 根据JSON条件字符串解析成FilterInfo
	 * 
	 * @param condition
	 * @return
	 * @throws BOSException
	 */
	@SuppressWarnings("unchecked")
	private FilterInfo conditionToFilterInfo(String condition) throws BOSException {
		Map<String, Object> params = null;
		JSONObject object = null;
		try {
			logger.info("解析条件字符串...");
			object = new JSONObject(condition);
		} catch (JSONException e) {
			throw new BOSException("解析JSON条件字符串出错!");
		}
		params = new HashMap<String, Object>();
		logger.info("解析条件...");
		for (Iterator<String> it = object.keys(); it.hasNext();) {
			String key = it.next();
			Object values = null;
			try {
				values = object.get(key);
			} catch (JSONException e) {
				throw new BOSException("解析JSON条件字符串出错!");
			}

			if (values instanceof String[]) {
				String[] pa = (String[]) values;
				if (pa.length > 0)
					params.put(key, stringArrayToSet(pa)); 
			} else if (values instanceof String) {
				String pa = (String) values;
				params.put(key, pa);
			}else if(values instanceof JSONArray){
				Set<String> v=new HashSet<String>();
				JSONArray pa=(JSONArray) values;
				for (int i = 0; i < pa.length(); i++) {
					try {
						v.add(pa.getString(i));
					} catch (JSONException e) {
						e.printStackTrace();
					}
				}
				params.put(key, v);
			}
		}

		// 构建条件
		FilterInfo fi = new FilterInfo();

		for (Iterator<String> it = params.keySet().iterator(); it.hasNext();) {
			String key = it.next();
			Object value = params.get(key);
			if (value instanceof String) {
				fi.getFilterItems().add(new FilterItemInfo(key, (String) value));
			} else if (value instanceof Set) {
				fi.getFilterItems().add(new FilterItemInfo(key, (Set) value,CompareType.INCLUDE));
			}
		}
		return fi;
	}

	private Set<Object> stringArrayToSet(String[] values) {
		Set<Object> va = new HashSet<Object>();
		for (int i = 0; i < values.length; i++) {
			va.add(values[i]);
		}
		return va;
	}
}
